package com.mashibing.juc.c_026_01_ThreadPool;

import java.time.LocalTime;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.atomic.AtomicInteger;

public class T12_ForkJoinPool {

    static int[] nums = new int[100*10000];
    static final int MAX_NUM = 5*10000;
    static Random r = new Random();

    static {
        for (int i = 0; i < nums.length; i++)
            nums[i] = r.nextInt(100);
        System.out.println("===>> " + Arrays.stream(nums).sum() + " <<==="); //stream api
        System.out.println();
    }

    static class AddAction extends RecursiveAction {

        static AtomicInteger index = new AtomicInteger(0);
        int start, end;

        AddAction(int s, int e) {
            start = s;
            end = e;
        }

        @Override
        protected void compute() {
            if (end - start <= MAX_NUM) {
                long sum = 0L;
                for (int i = start; i < end; i++) sum += nums[i];
                System.out.printf("\033[32m %s ===>> %s ===>> index[%s]\n ===>> from[%s] ===>> to:[%s] ===>> %s \033[0m\n",
                        Thread.currentThread().getName(), LocalTime.now(), index.getAndIncrement(), start, end, sum);
                System.out.println();
            } else {
                int middle = start + (end - start) / 2;
                AddAction subTask1 = new AddAction(start, middle);
                AddAction subTask2 = new AddAction(middle, end);
                subTask1.fork();
                subTask2.fork();
            }
        }

    }

    static class AddTask extends RecursiveTask<Long> {

        int start, end;

        AddTask(int s, int e) {
            start = s;
            end = e;
        }

        @Override
        protected Long compute() {
            if (end - start <= MAX_NUM) {
                long sum = 0L;
                for (int i = start; i < end; i++) sum += nums[i];
                return sum;
            }

            int middle = start + (end - start) / 2;
            AddTask subTask1 = new AddTask(start, middle);
            AddTask subTask2 = new AddTask(middle, end);
            subTask1.fork();
            subTask2.fork();

            return subTask1.join() + subTask2.join();
        }

    }

    public static void main(String[] args) throws Exception {
		ForkJoinPool forkJoinPool = new ForkJoinPool();
		AddAction task = new AddAction(0, nums.length);
		forkJoinPool.execute(task);

        /*ForkJoinPool forkJoinPool = new ForkJoinPool();
        AddTaskRet task = new AddTaskRet(0, nums.length);
        forkJoinPool.execute(task);
        System.out.println(task.join());*/

        System.in.read();
    }

}
